/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sd.chat;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Vector;
import java.util.logging.Level;

/**
 *
 * @author Old
 */
public class RMIConnectionHandlerCli extends UnicastRemoteObject implements ClientHandlerInterface, Runnable, RMIHandlerInterface, Serializable {

    private final Vector<TCPMsg> sendQueue;
    private final Vector<TCPMsg> receiveQueue;
    private ClientManager myManager;
    private boolean logged = false;
    private Utilizador loggedUser;
    private boolean readyToSend = false;
    private boolean messageReceived = false;
    private boolean shutdown = false;
    private Logger log = new Logger(true);
    private RMIHandlerInterface cliCon;

    public RMIConnectionHandlerCli(ClientManager myMan) throws RemoteException {
        super();
        this.myManager = myMan;
        this.sendQueue = new Vector<TCPMsg>();
        this.receiveQueue = new Vector<TCPMsg>();
    }

    public void setcliCon(RMIHandlerInterface cli) {
        this.cliCon = cli;
    }

    @Override
    public void run() {
        while (!shutdown) {
            dispatchMessages();
        }
        log.outln("RMIConnectionHandlerCli terminating...");
        try {
            this.cliCon.unexpectedShutdown();
            log.outln("RMIConnectionHandlerCli shuting down other end...");
        } catch (RemoteException ex) {
            log.erro("RMIConnectionHandlerCli shuting down other end...");
        }
        this.cliCon = null;
        System.gc();
        System.runFinalization();
    }

    public synchronized void dispatchMessages() {
        //while (!messageReceived) {
        if (this.receiveQueue.isEmpty()) {
            try {
                log.outln("RMIConnectionHandlerCli dispatchMessages preparing to wait");
                wait();
            } catch (InterruptedException e) {
                log.erro("interruptedException caught");
            }
            log.outln("RMIConnectionHandlerCli dispatchMessages resuming");
        }

        while (!this.receiveQueue.isEmpty()) {
            TCPMsg rcvMsg = this.receiveQueue.remove(0);
            myManager.newMessageReceived(rcvMsg);
        }
        messageReceived = false;
        //}
    }

    @Override
    public synchronized void addMsg(TCPMsg newMsg) {
        try {
            this.cliCon.addReceivedMessage(newMsg);
        } catch (RemoteException ex) {
            this.unexpectedShutdown();
            log.erro("RemoteException:" + ex);
        }
    }
    
    @Override
    public synchronized boolean canSend() throws RemoteException {
        return true;
    }
    
    @Override
    public synchronized boolean canAddMsg(){
        boolean retorno = false;
        try {
            retorno = this.cliCon.canSend();
        } catch (RemoteException ex) {
            this.unexpectedShutdown();
            log.erro("RemoteException:" + ex);
        }
        return retorno;
    }

    @Override
    public synchronized void setShutdown(boolean shutdown) {
        this.shutdown = shutdown;
        notifyAll();
    }

    @Override
    public Utilizador getLoggedUser() {
        return loggedUser;
    }

    @Override
    public void setLoggedUser(Utilizador loggedUser) {
        this.loggedUser = loggedUser;
    }

    public ClientManager getMyManager() {
        return myManager;
    }

    public void setMyManager(ClientManager myManager) {
        this.myManager = myManager;
    }

    @Override
    public boolean isLogged() {
        return logged;
    }

    @Override
    public void setLogged(boolean logged) {
        this.logged = logged;
    }

    public synchronized boolean getMsgReceived() {
        return this.messageReceived;
    }

    public synchronized void setMsgReceived(boolean state) {
        this.messageReceived = state;
    }

    @Override
    public synchronized void addReceivedMessage(TCPMsg message) {
        receiveQueue.add(message);
        this.messageReceived = true;
        notifyAll();
    }

    @Override
    public synchronized Vector<TCPMsg> getSendQueue() {
        Vector<TCPMsg> tempVec = new Vector<TCPMsg>();
        tempVec.addAll(this.sendQueue);
        return tempVec;
    }

    @Override
    public synchronized void setSendQueue(Vector<TCPMsg> backupSendQueue) {
        this.sendQueue.addAll(backupSendQueue);
    }

    @Override
    public synchronized void unexpectedShutdown() {
        myManager.connectionLost();
        this.setShutdown(true);
    }
}